package com.wangyg.flourfactory.controller;

import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.wangyg.flourfactory.outer.ICallBreadStore;
import com.wangyg.flourfactory.outer.ICallFlourFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * Created by wangyg6 on 2019/5/21 17:22.
 */
@RestController
public class TestHystrixController {
	@Autowired
	@Qualifier("lbRestTemplate")
	RestTemplate lbRestTemplate;
	@Autowired
	@Qualifier("restTemplate")
	RestTemplate restTemplate;
	@Autowired
	LoadBalancerClient client;
	@Autowired
	EurekaClient client2;
	@Autowired
	ICallBreadStore breadStore;
	//此处很神奇，ICallFlourFactory有两个实现类，flourFactory2和FeignClient动态生成的类，但是默认它可以注入Feign生成的类
	//如果加qualifier则无法注入
	@Autowired
	ICallFlourFactory flourfactory;

	/**
	 *ribbon  @loadbalanced注解实现的load balance resttemplate是否支持熔断
	 * @return
	 */
	@GetMapping("/hystrix1")
	@HystrixCommand(fallbackMethod = "defaultFallBack", commandProperties = {
			@HystrixProperty(name = "execution.isolation.strategy", value = "SEMAPHORE") })
	public String testFallBack() {
		String url = "http://breadStore/bread_store/test/hystrix";
		return lbRestTemplate.getForObject(url, String.class);
	}

	/**
	 * ribbon LoadBalancerClient是否支持熔断
	 * @return
	 */
	@GetMapping("/hystrix2")
	@HystrixCommand(fallbackMethod = "defaultFallBack", commandProperties = {
			@HystrixProperty(name = "execution.isolation.strategy", value = "SEMAPHORE") })
	public String testFallBack2() {
		//负载均衡方式获取远程serviceInstance
		ServiceInstance breadStore = client.choose("breadStore");
		String url = "http://" + breadStore.getHost() + ":" + breadStore.getPort() + "/bread_store/test/hystrix";
		return restTemplate.getForObject(url, String.class);
	}

	/**
	 * 	验证非负载均衡客户端，是否可以熔断
	 * @return
	 */
	@GetMapping("/hystrix3")
	@HystrixCommand(fallbackMethod = "defaultFallBack", commandProperties = {
			@HystrixProperty(name = "execution.isolation.strategy", value = "SEMAPHORE") })
	public String testFallBack3() {
		//负载均衡方式获取远程serviceInstance
		InstanceInfo breadStore = client2.getNextServerFromEureka("breadStore", false);
		String url = breadStore.getHomePageUrl() + "/bread_store/test/hystrix";
		return restTemplate.getForObject(url, String.class);
	}

	/**

	 * Hystrix隔离策略相关的参数 execution.isolation.strategy= THREAD|SEMAPHORE
	 * 通过cglib动态代理实现
	 * @return
	 */
	public String defaultFallBack(Throwable e) throws Exception {
		//		throw new Exception(e.getMessage());
		return "This is a hystrix fallback message.exception is:" + e.getMessage() + e.getStackTrace()[0];
	}

	/**
	 * 	Feign集成负载均衡，Hystrix熔断
	 * 	fallback使用的内部类
	 * @return
	 */
	@GetMapping("/hystrix4")
	public String testFallBack4() {
		return breadStore.getHystrixMsg();
	}

	/**
	 * 	Feign集成负载均衡，Hystrix熔断
	 * 	fallback使用的bean注入
	 * @return
	 */
	@GetMapping("/hystrix5")
	public Integer testFallBack5() {
		return flourfactory.getFlourNum(7);
	}
}